import "./style.css";

import {
  Audio,
  AudioLoader,
  AudioListener,
  Scene,
  Clock,
  Color,
  AmbientLight,
  WebGLRenderer,
  DirectionalLight,
  PerspectiveCamera,
} from 'three';

import { MMDLoader } from 'three/examples/jsm/loaders/MMDLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { MMDAnimationHelper } from 'three/examples/jsm/animation/MMDAnimationHelper.js';
import * as Ammo from 'ammo.js';

function onProgress(xhr) {
  console.log(( xhr.loaded / xhr.total * 100 ) + '% loaded');
}
function onError(err) {
  console.log('Error:', err);
}

const clock = new Clock();

let renderId = null;
let mesh;
let ready = false;
let loaded = false;
let audio = null;

const container = document.createElement('div');
const startBtn = document.getElementById('start_btn');
const pauseBtn  = document.getElementById('pause_btn');
document.body.appendChild(container);


Ammo().then(() => {
  init();
});

function init() {
  const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
  camera.position.set(0, 0, 20);

  const scene = new Scene();
  scene.background = new Color(0xffffff);

  const ambient = new AmbientLight(0x666666);
  scene.add(ambient);

  const directionalLight = new DirectionalLight(0x887766);
  directionalLight.position.set(-1, 1, 1).normalize();
  scene.add(directionalLight);

  let renderer = new WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(1);
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);

  const listener = new AudioListener();
  camera.add(listener);
  scene.add(camera);

  const controls = new OrbitControls(camera, renderer.domElement);
  controls.target.set(0, 10, 0);
  controls.update();

  const modelFile = 'models/fischl.pmx';
  const vmdFiles = [ 'vmds/wavefile_v2.vmd' ];
  const cameraFiles = [ 'vmds/wavefile_camera.vmd' ];
  const audioFile = 'audios/wavefile_short.mp3';
  const audioParams = { delayTime: 160 * 1 / 30 };

  const loader = new MMDLoader();
  const helper = new MMDAnimationHelper();
  loader.loadWithAnimation(
    modelFile, vmdFiles,
    function(mmd) {
      mesh = mmd.mesh;
      helper.add(mesh, {
        animation: mmd.animation,
        physics: true
      });
      loader.loadAnimation(cameraFiles, camera, function(cameraAnimation) {
        helper.add(camera, {
          animation: cameraAnimation
        });
        new AudioLoader().load(audioFile, function(buffer) {
          audio = new Audio(listener).setBuffer(buffer);
          helper.add(audio, audioParams);
          scene.add(mesh);
          loaded = true;
          render();
        }, null, onError);
      }, null, onError);
    },
    onProgress,
    onError
  );


  function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    // controls.update();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }

  window.addEventListener('resize', onWindowResize, false);

  function animate() {
    renderId = requestAnimationFrame(animate);
    // controls.update();
    render();
  }

  function cancelAnimation() {
    cancelAnimationFrame(renderId);
  }

  function pauseAndResumeAnimation() {
    if (!loaded) {
      return;
    }
    if (ready) {
      // 暂停
      audio.pause();
      clock.stop();
      pauseBtn.innerText = "继续";
    } else {
      // 继续
      audio.play();
      clock.start();
      pauseBtn.innerText = "暂停";
    }
    controls.enabled = ready;
    ready = !ready;
  }

  function startAnimation() {
    if (loaded) {
      ready = true;
      controls.enabled = false;
    }
    animate();
  }


  function render() {
    if (ready) {
      helper.update(clock.getDelta());
    }
    renderer.render(scene, camera);
  }
  controls.addEventListener('change', render);

  startBtn.addEventListener("click", startAnimation);
  pauseBtn.addEventListener("click", pauseAndResumeAnimation);
  render();
}
